home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / C / BAWK.ZIP / BAWKACT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-07  |  7.8 KB  |  422 lines

  1. /*
  2.  * Bawk C actions compiler
  3.  */
  4. #include <stdio.h>
  5. #include "bawk.h"
  6.  
  7. act_compile(actbuf)
  8.     char *actbuf;        /* where tokenized actions are compiled into */
  9. {
  10.     Where = ACTION;
  11.     return stmt_compile(actbuf);
  12. }
  13.  
  14. pat_compile(actbuf)
  15.     char *actbuf;        /* where tokenized actions are compiled into */
  16. {
  17.     Where = PATTERN;
  18.     return stmt_compile(actbuf);
  19. }
  20.  
  21. stmt_compile(actbuf)
  22.     char *actbuf;        /* where tokenized actions are compiled into */
  23. {
  24.     /*
  25.      * Read and tokenize C actions from current input file into the
  26.      * action buffer.  Strip out comments and whitespace in the process. 
  27.      */
  28.     char *actptr,        /* actbuf pointer */
  29.     *cp,            /* work pointer */
  30.      buf[MAXLINELEN];    /* string buffer */
  31.     int braces,        /* counts '{}' pairs - return when 0 */
  32.      parens,        /* counts '()' pairs */
  33.      i,            /* temp */
  34.      c;            /* current input character */
  35.  
  36.     braces = parens = 0;
  37.     actptr = actbuf;
  38.     while ((c = getcharacter()) != -1) {
  39.         /*
  40.          * Skip over spaces, tabs and newlines 
  41.          */
  42.         if (c == ' ' || c == '\t' || c == '\n')
  43.             continue;
  44.         if (c == '#') {
  45.             /*
  46.              * Skip comments.  Comments start with a '#' and end
  47.              * at the next newline. 
  48.              */
  49.             while ((c = getcharacter()) != -1 && c != '\n');
  50.             continue;
  51.         }
  52.  
  53.         if (c == '{') {
  54.             if (Where == PATTERN) {
  55.                 /*
  56.                  * We're compiling a pattern. The '{' marks
  57.                  * the beginning of an action statement. Push
  58.                  * the character back and return. 
  59.                  */
  60.                 ungetcharacter('{');
  61.                 break;
  62.             }
  63.             else {
  64.                 /*
  65.                  * We must be compiling an action statement.
  66.                  * '{'s mark beginning of action or compound
  67.                  * statements. 
  68.                  */
  69.                 ++braces;
  70.                 *actptr++ = T_LBRACE;
  71.             }
  72.         }
  73.         else if (c == '}') {
  74.             *actptr++ = T_RBRACE;
  75.             if (!--braces)
  76.                 /*
  77.                  * Found the end of the action string 
  78.                  */
  79.                 break;
  80.         }
  81.         else if (c == '(') {
  82.             ++parens;
  83.             *actptr++ = T_LPAREN;
  84.         }
  85.         else if (c == ')') {
  86.             if (--parens < 0)
  87.                 error("mismatched '()'", ACT_ERROR);
  88.             *actptr++ = T_RPAREN;
  89.         }
  90.         else if (c == ',' && !braces && !parens && Where == PATTERN) {
  91.             /*
  92.              * found a comma outside of any braces or parens-
  93.              * this must be a regular expression seperator. 
  94.              */
  95.             ungetcharacter(',');
  96.             break;
  97.         }
  98.  
  99.         /*
  100.          * Check if it's a regular expression: 
  101.          */
  102.         else if (c == '/') {
  103.             /*
  104.              * A '/' inside a pattern string starts a regular
  105.              * expression.  Inside action strings, a '/' is the
  106.              * division operator. 
  107.              */
  108.             if (Where == PATTERN)
  109.                 goto dopattern;
  110.             else
  111.                 *actptr++ = T_DIV;
  112.         }
  113.         else if (c == '@') {
  114.     dopattern:
  115.             /*
  116.              * Within action strings, only the '@' may be used to
  117.              * delimit regular expressions 
  118.              */
  119.             *actptr++ = T_REGEXP;
  120.             ungetcharacter(c);
  121.             actptr += re_compile(actptr);
  122.         }
  123.  
  124.         /*
  125.          * symbol, string or constant: 
  126.          */
  127.         else if (alpha(c)) {
  128.             /*
  129.              * It's a symbol reference. Copy the symbol into
  130.              * string buffer. 
  131.              */
  132.             cp = buf;
  133.             do
  134.                 *cp++ = c;
  135.             while ((c = getcharacter()) != -1 && alphanum(c));
  136.             ungetcharacter(c);
  137.             *cp = 0;
  138.             /*
  139.              * Check if a keyword, builtin function or variable. 
  140.              */
  141.             if (c = iskeyword(buf))
  142.                 *actptr++ = c;
  143.             else if (i = isfunction(buf)) {
  144.                 *actptr++ = T_FUNCTION;
  145.                 storeint(actptr, i);
  146.                 actptr += sizeof(i);
  147.             }
  148.             else {
  149.                 /*
  150.                  * It's a symbol name. 
  151.                  */
  152.                 *actptr++ = T_VARIABLE;
  153.             if (!(cp = (char *) findvar(buf)))
  154.                     cp = (char *) addvar(buf);
  155.                 storeptr(actptr, cp);
  156.                 actptr += sizeof(cp);
  157.             }
  158.         }
  159.  
  160.         else if (c == '"') {
  161.             /*
  162.              * It's a string constant 
  163.              */
  164.             *actptr++ = T_STRING;
  165.             actptr = str_compile(actptr, '"');
  166.         }
  167.         else if (c == '\'') {
  168.             /*
  169.              * It's a character constant 
  170.              */
  171.             *actptr++ = T_CONSTANT;
  172.             str_compile(buf, '\'');
  173.             storeint(actptr, *buf);
  174.             actptr += sizeof(i);
  175.         }
  176.  
  177.         else if (num(c)) {
  178.             /*
  179.              * It's a numeric constant 
  180.              */
  181.             *actptr++ = T_CONSTANT;
  182.             cp = buf;
  183.             do
  184.                 *cp++ = c;
  185.             while ((c = getcharacter()) != -1 && num(c));
  186.             ungetcharacter(c);
  187.             *cp = 0;
  188.             storeint(actptr, atoi(buf));
  189.             actptr += sizeof(i);
  190.         }
  191.  
  192.         /*
  193.          * unary operator: 
  194.          */
  195.         else if (c == '$')
  196.             *actptr++ = T_DOLLAR;
  197.  
  198.         /*
  199.          * or binary operator: 
  200.          */
  201.         else if (c == '=') {
  202.             if ((c = getcharacter()) == '=')
  203.                 *actptr++ = T_EQ;
  204.             else {
  205.                 ungetcharacter(c);
  206.                 *actptr++ = T_ASSIGN;
  207.             }
  208.         }
  209.  
  210.         else if (c == '!') {
  211.             if ((c = getcharacter()) == '=')
  212.                 *actptr++ = T_NE;
  213.             else {
  214.                 ungetcharacter(c);
  215.                 *actptr++ = T_LNOT;
  216.             }
  217.         }
  218.  
  219.         else if (c == '<') {
  220.             if ((c = getcharacter()) == '<')
  221.                 *actptr++ = T_SHL;
  222.             else if (c == '=')
  223.                 *actptr++ = T_LE;
  224.             else {
  225.                 ungetcharacter(c);
  226.                 *actptr++ = T_LT;
  227.             }
  228.         }
  229.  
  230.         else if (c == '>') {
  231.             if ((c = getcharacter()) == '>')
  232.                 *actptr++ = T_SHR;
  233.             else if (c == '=')
  234.                 *actptr++ = T_GE;
  235.             else {
  236.                 ungetcharacter(c);
  237.                 *actptr++ = T_GT;
  238.             }
  239.         }
  240.  
  241.         else if (c == '&') {
  242.             if ((c = getcharacter()) == '&')
  243.                 *actptr++ = T_LAND;
  244.             else {
  245.                 ungetcharacter(c);
  246.                 *actptr++ = T_AND;
  247.             }
  248.         }
  249.  
  250.         else if (c == '|') {
  251.             if ((c = getcharacter()) == '|')
  252.                 *actptr++ = T_LIOR;
  253.             else {
  254.                 ungetcharacter(c);
  255.                 *actptr++ = T_IOR;
  256.             }
  257.         }
  258.         else if (c == '+') {
  259.             if ((c = getcharacter()) == '+')
  260.                 *actptr++ = T_INCR;
  261.             else {
  262.                 ungetcharacter(c);
  263.                 *actptr++ = T_ADD;
  264.             }
  265.         }
  266.  
  267.         else if (c == '-') {
  268.             if ((c = getcharacter()) == '-')
  269.                 *actptr++ = T_DECR;
  270.             else {
  271.                 ungetcharacter(c);
  272.                 *actptr++ = T_SUB;
  273.             }
  274.         }
  275.  
  276.         /*
  277.          * punctuation 
  278.          */
  279.         else if (instr(c, "[](),;*/%+-^~"))
  280.             *actptr++ = c;
  281.  
  282.         else {
  283.             /*
  284.              * Bad character in input line 
  285.              */
  286.             error("lexical error", ACT_ERROR);
  287.         }
  288.  
  289.         if (actptr >= Workbuf + MAXWORKBUFLEN)
  290.             error("action too long", MEM_ERROR);
  291.     }
  292.     if (braces || parens)
  293.         error("mismatched '{}' or '()'", ACT_ERROR);
  294.  
  295.     *actptr++ = T_EOF;
  296.  
  297.     return actptr - actbuf;
  298. }
  299.  
  300. char *
  301. str_compile(str, delim)
  302.     char *str, delim;
  303. {
  304.     /*
  305.      * Compile a string from current input file into the given string
  306.      * buffer.  Stop when input character is the delimiter in "delim".
  307.      * Returns a pointer to the first character after the string. 
  308.      */
  309.     int c;
  310.     char buf[MAXLINELEN];
  311.  
  312.     while ((c = getcharacter()) != -1 && c != delim) {
  313.         if (c == '\\') {
  314.             switch (c = getcharacter()) {
  315.             case -1:
  316.                 goto err;
  317.             case 'b':
  318.                 c = '\b';
  319.                 break;
  320.             case 'n':
  321.                 c = '\n';
  322.                 break;
  323.             case 't':
  324.                 c = '\t';
  325.                 break;
  326.             case 'f':
  327.                 c = '\f';
  328.                 break;
  329.             case 'r':
  330.                 c = '\r';
  331.                 break;
  332.             case '0':
  333.             case '1':
  334.             case '2':
  335.             case '3':
  336.                 *buf = c;
  337.                 for (c = 1; c < 3; ++c) {
  338.                     if ((buf[c] = getcharacter()) == -1)
  339.                         goto err;
  340.                 }
  341.                 buf[c] = 0;
  342.                 sscanf(buf, "%o", &c);
  343.                 break;
  344.             case '\n':
  345.                 if (getcharacter() == -1)
  346.                     goto err;
  347.             default:
  348.                 if ((c = getcharacter()) == -1)
  349.                     goto err;
  350.             }
  351.         }
  352.         *str++ = c;
  353.     }
  354.     *str++ = 0;
  355.  
  356.     return (str);
  357. err:
  358.     sprintf(buf, "missing %c delimiter", delim);
  359.     error(buf, 4);
  360. }
  361.  
  362. storeint(ip, i)
  363.     int *ip, i;
  364. {
  365.     return *ip = i;
  366. }
  367.  
  368. char *
  369. storeptr(pp, p)
  370.     char **pp, *p;
  371. {
  372.     return (*pp = p);
  373. }
  374.  
  375. fetchint(ip)
  376.     int *ip;
  377. {
  378.     return *ip;
  379. }
  380.  
  381. char *
  382. fetchptr(pp)
  383.     char **pp;
  384. {
  385.     return *pp;
  386. }
  387.  
  388. getoken()
  389. {
  390.     char *cp;
  391.     int i;
  392.  
  393.     switch (Token = *Actptr++) {
  394.     case T_STRING:
  395.     case T_REGEXP:
  396.         Value.dptr = Actptr;
  397.         Actptr += strlen(Actptr) + 1;
  398.         break;
  399.     case T_VARIABLE:
  400.         Value.dptr = fetchptr(Actptr);
  401.         Actptr += sizeof(cp);
  402.         break;
  403.     case T_FUNCTION:
  404.     case T_CONSTANT:
  405.         Value.ival = fetchint(Actptr);
  406.         Actptr += sizeof(i);
  407.         break;
  408.     case T_EOF:
  409.         --Actptr;
  410.     default:
  411.         Value.dptr = 0;
  412.     }
  413.  
  414. #ifdef DEBUG
  415.     if (Debug > 1)
  416.         printf("Token='%c' (0x%x), Value=%d\n",
  417.                Token, Token, Value.ival);
  418. #endif
  419.  
  420.     return Token;
  421. }
  422.